From: Tim Deegan Date: Thu, 8 Sep 2011 14:13:06 +0000 (+0100) Subject: x86/mm: adjust p2m interface to return superpage sizes X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~9913 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22?a=commitdiff_plain;h=a18dd4934f2d67616a0c5a20c8a571d05db57bfc;p=xen.git x86/mm: adjust p2m interface to return superpage sizes Signed-off-by: Christoph Egger Signed-off-by: Tim Deegan Committed-by: Tim Deegan --- diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 43994d1465..6df24ea87b 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -1216,7 +1216,7 @@ int hvm_hap_nested_page_fault(unsigned long gpa, } p2m = p2m_get_hostp2m(v->domain); - mfn = gfn_to_mfn_type_p2m(p2m, gfn, &p2mt, &p2ma, p2m_guest); + mfn = gfn_to_mfn_type_p2m(p2m, gfn, &p2mt, &p2ma, p2m_guest, NULL); /* Check access permissions first, then handle faults */ if ( access_valid && (mfn_x(mfn) != INVALID_MFN) ) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 8d9ee8747f..479ad17103 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -1160,7 +1160,7 @@ static void svm_do_nested_pgfault(struct vcpu *v, p2m = p2m_get_p2m(v); _d.gpa = gpa; _d.qualification = 0; - _d.mfn = mfn_x(gfn_to_mfn_type_p2m(p2m, gfn, &_d.p2mt, &p2ma, p2m_query)); + _d.mfn = mfn_x(gfn_to_mfn_type_p2m(p2m, gfn, &_d.p2mt, &p2ma, p2m_query, NULL)); __trace_var(TRC_HVM_NPF, 0, sizeof(_d), &_d); } @@ -1180,7 +1180,7 @@ static void svm_do_nested_pgfault(struct vcpu *v, if ( p2m == NULL ) p2m = p2m_get_p2m(v); /* Everything else is an error. */ - mfn = gfn_to_mfn_type_p2m(p2m, gfn, &p2mt, &p2ma, p2m_guest); + mfn = gfn_to_mfn_type_p2m(p2m, gfn, &p2mt, &p2ma, p2m_guest, NULL); gdprintk(XENLOG_ERR, "SVM violation gpa %#"PRIpaddr", mfn %#lx, type %i\n", gpa, mfn_x(mfn), p2mt); diff --git a/xen/arch/x86/mm/guest_walk.c b/xen/arch/x86/mm/guest_walk.c index 2f9327714c..7491b77f61 100644 --- a/xen/arch/x86/mm/guest_walk.c +++ b/xen/arch/x86/mm/guest_walk.c @@ -95,7 +95,7 @@ static inline void *map_domain_gfn(struct p2m_domain *p2m, p2m_access_t a; /* Translate the gfn, unsharing if shared */ - *mfn = gfn_to_mfn_type_p2m(p2m, gfn_x(gfn), p2mt, &a, p2m_unshare); + *mfn = gfn_to_mfn_type_p2m(p2m, gfn_x(gfn), p2mt, &a, p2m_unshare, NULL); if ( p2m_is_paging(*p2mt) ) { ASSERT(!p2m_is_nestedp2m(p2m)); diff --git a/xen/arch/x86/mm/hap/guest_walk.c b/xen/arch/x86/mm/hap/guest_walk.c index f49fd87a16..24ff59c196 100644 --- a/xen/arch/x86/mm/hap/guest_walk.c +++ b/xen/arch/x86/mm/hap/guest_walk.c @@ -59,7 +59,7 @@ unsigned long hap_p2m_ga_to_gfn(GUEST_PAGING_LEVELS)( /* Get the top-level table's MFN */ top_mfn = gfn_to_mfn_type_p2m(p2m, cr3 >> PAGE_SHIFT, - &p2mt, &p2ma, p2m_unshare); + &p2mt, &p2ma, p2m_unshare, NULL); if ( p2m_is_paging(p2mt) ) { ASSERT(!p2m_is_nestedp2m(p2m)); @@ -92,7 +92,7 @@ unsigned long hap_p2m_ga_to_gfn(GUEST_PAGING_LEVELS)( if ( missing == 0 ) { gfn_t gfn = guest_l1e_get_gfn(gw.l1e); - gfn_to_mfn_type_p2m(p2m, gfn_x(gfn), &p2mt, &p2ma, p2m_unshare); + gfn_to_mfn_type_p2m(p2m, gfn_x(gfn), &p2mt, &p2ma, p2m_unshare, NULL); if ( p2m_is_paging(p2mt) ) { ASSERT(!p2m_is_nestedp2m(p2m)); diff --git a/xen/arch/x86/mm/hap/nested_hap.c b/xen/arch/x86/mm/hap/nested_hap.c index ebd42cef90..2bab9e71f2 100644 --- a/xen/arch/x86/mm/hap/nested_hap.c +++ b/xen/arch/x86/mm/hap/nested_hap.c @@ -136,7 +136,8 @@ nestedhap_walk_L0_p2m(struct p2m_domain *p2m, paddr_t L1_gpa, paddr_t *L0_gpa) p2m_access_t p2ma; /* walk L0 P2M table */ - mfn = gfn_to_mfn_type_p2m(p2m, L1_gpa >> PAGE_SHIFT, &p2mt, &p2ma, p2m_query); + mfn = gfn_to_mfn_type_p2m(p2m, L1_gpa >> PAGE_SHIFT, &p2mt, &p2ma, + p2m_query, NULL); if ( p2m_is_paging(p2mt) || p2m_is_shared(p2mt) || !p2m_is_ram(p2mt) ) return NESTEDHVM_PAGEFAULT_ERROR; diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c index 701f33d87a..9ccf14617f 100644 --- a/xen/arch/x86/mm/p2m-ept.c +++ b/xen/arch/x86/mm/p2m-ept.c @@ -507,7 +507,7 @@ out: /* Read ept p2m entries */ static mfn_t ept_get_entry(struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t, p2m_access_t* a, - p2m_query_t q) + p2m_query_t q, unsigned int *page_order) { struct domain *d = p2m->domain; ept_entry_t *table = map_domain_page(ept_get_asr(d)); @@ -594,6 +594,9 @@ static mfn_t ept_get_entry(struct p2m_domain *p2m, ((1 << (i * EPT_TABLE_ORDER)) - 1)); mfn = _mfn(split_mfn); } + + if ( page_order ) + *page_order = i * EPT_TABLE_ORDER; } out: diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c index 65fa3c9716..7e48e7e3b4 100644 --- a/xen/arch/x86/mm/p2m-pt.c +++ b/xen/arch/x86/mm/p2m-pt.c @@ -503,7 +503,8 @@ static int p2m_pod_check_and_populate(struct p2m_domain *p2m, unsigned long gfn, /* Read the current domain's p2m table (through the linear mapping). */ static mfn_t p2m_gfn_to_mfn_current(struct p2m_domain *p2m, unsigned long gfn, p2m_type_t *t, - p2m_access_t *a, p2m_query_t q) + p2m_access_t *a, p2m_query_t q, + unsigned int *page_order) { mfn_t mfn = _mfn(INVALID_MFN); p2m_type_t p2mt = p2m_mmio_dm; @@ -567,6 +568,8 @@ pod_retry_l3: else p2mt = p2m_mmio_dm; + if ( page_order ) + *page_order = PAGE_ORDER_1G; goto out; } #endif @@ -620,6 +623,8 @@ pod_retry_l2: else p2mt = p2m_mmio_dm; + if ( page_order ) + *page_order = PAGE_ORDER_2M; goto out; } @@ -669,6 +674,8 @@ pod_retry_l1: p2mt = p2m_mmio_dm; } + if ( page_order ) + *page_order = PAGE_ORDER_4K; out: *t = p2mt; return mfn; @@ -676,7 +683,8 @@ out: static mfn_t p2m_gfn_to_mfn(struct p2m_domain *p2m, unsigned long gfn, - p2m_type_t *t, p2m_access_t *a, p2m_query_t q) + p2m_type_t *t, p2m_access_t *a, p2m_query_t q, + unsigned int *page_order) { mfn_t mfn; paddr_t addr = ((paddr_t)gfn) << PAGE_SHIFT; @@ -699,7 +707,7 @@ p2m_gfn_to_mfn(struct p2m_domain *p2m, unsigned long gfn, /* Use the fast path with the linear mapping if we can */ if ( p2m == p2m_get_hostp2m(current->domain) ) - return p2m_gfn_to_mfn_current(p2m, gfn, t, a, q); + return p2m_gfn_to_mfn_current(p2m, gfn, t, a, q, page_order); mfn = pagetable_get_mfn(p2m_get_pagetable(p2m)); @@ -753,6 +761,8 @@ pod_retry_l3: unmap_domain_page(l3e); ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t)); + if ( page_order ) + *page_order = PAGE_ORDER_1G; return (p2m_is_valid(*t)) ? mfn : _mfn(INVALID_MFN); } @@ -787,6 +797,8 @@ pod_retry_l2: unmap_domain_page(l2e); ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t)); + if ( page_order ) + *page_order = PAGE_ORDER_2M; return (p2m_is_valid(*t)) ? mfn : _mfn(INVALID_MFN); } @@ -817,6 +829,8 @@ pod_retry_l1: unmap_domain_page(l1e); ASSERT(mfn_valid(mfn) || !p2m_is_ram(*t)); + if ( page_order ) + *page_order = PAGE_ORDER_4K; return (p2m_is_valid(*t) || p2m_is_grant(*t)) ? mfn : _mfn(INVALID_MFN); } diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index c90677443c..c3c8c87c37 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -307,7 +307,7 @@ void p2m_teardown(struct p2m_domain *p2m) #ifdef __x86_64__ for ( gfn=0; gfn < p2m->max_mapped_pfn; gfn++ ) { - mfn = gfn_to_mfn_type_p2m(p2m, gfn, &t, &a, p2m_query); + mfn = gfn_to_mfn_type_p2m(p2m, gfn, &t, &a, p2m_query, NULL); if ( mfn_valid(mfn) && (t == p2m_ram_shared) ) { ASSERT(!p2m_is_nestedp2m(p2m)); @@ -372,7 +372,7 @@ p2m_remove_page(struct p2m_domain *p2m, unsigned long gfn, unsigned long mfn, { for ( i = 0; i < (1UL << page_order); i++ ) { - mfn_return = p2m->get_entry(p2m, gfn + i, &t, &a, p2m_query); + mfn_return = p2m->get_entry(p2m, gfn + i, &t, &a, p2m_query, NULL); if ( !p2m_is_grant(t) ) set_gpfn_from_mfn(mfn+i, INVALID_M2P_ENTRY); ASSERT( !p2m_is_valid(t) || mfn + i == mfn_x(mfn_return) ); @@ -878,7 +878,7 @@ void p2m_mem_access_check(unsigned long gpa, bool_t gla_valid, unsigned long gla /* First, handle rx2rw conversion automatically */ p2m_lock(p2m); - mfn = p2m->get_entry(p2m, gfn, &p2mt, &p2ma, p2m_query); + mfn = p2m->get_entry(p2m, gfn, &p2mt, &p2ma, p2m_query, NULL); if ( access_w && p2ma == p2m_access_rx2rw ) { @@ -1036,7 +1036,7 @@ int p2m_get_mem_access(struct domain *d, unsigned long pfn, return 0; } - mfn = p2m->get_entry(p2m, pfn, &t, &a, p2m_query); + mfn = p2m->get_entry(p2m, pfn, &t, &a, p2m_query, NULL); if ( mfn_x(mfn) == INVALID_MFN ) return -ESRCH; diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h index e4c118ce46..159c8cabf6 100644 --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -233,7 +233,8 @@ struct p2m_domain { unsigned long gfn, p2m_type_t *p2mt, p2m_access_t *p2ma, - p2m_query_t q); + p2m_query_t q, + unsigned int *page_order); void (*change_entry_type_global)(struct p2m_domain *p2m, p2m_type_t ot, p2m_type_t nt); @@ -303,10 +304,14 @@ struct p2m_domain *p2m_get_p2m(struct vcpu *v); /* Read a particular P2M table, mapping pages as we go. Most callers * should _not_ call this directly; use the other gfn_to_mfn_* functions * below unless you know you want to walk a p2m that isn't a domain's - * main one. */ + * main one. + * If the lookup succeeds, the return value is != INVALID_MFN and + * *page_order is filled in with the order of the superpage (if any) that + * the entry was found in. */ static inline mfn_t gfn_to_mfn_type_p2m(struct p2m_domain *p2m, unsigned long gfn, - p2m_type_t *t, p2m_access_t *a, p2m_query_t q) + p2m_type_t *t, p2m_access_t *a, p2m_query_t q, + unsigned int *page_order) { mfn_t mfn; @@ -318,14 +323,14 @@ gfn_to_mfn_type_p2m(struct p2m_domain *p2m, unsigned long gfn, return _mfn(gfn); } - mfn = p2m->get_entry(p2m, gfn, t, a, q); + mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order); #ifdef __x86_64__ if ( q == p2m_unshare && p2m_is_shared(*t) ) { ASSERT(!p2m_is_nestedp2m(p2m)); mem_sharing_unshare_page(p2m->domain, gfn, 0); - mfn = p2m->get_entry(p2m, gfn, t, a, q); + mfn = p2m->get_entry(p2m, gfn, t, a, q, page_order); } #endif @@ -349,7 +354,7 @@ static inline mfn_t gfn_to_mfn_type(struct domain *d, p2m_query_t q) { p2m_access_t a; - return gfn_to_mfn_type_p2m(p2m_get_hostp2m(d), gfn, t, &a, q); + return gfn_to_mfn_type_p2m(p2m_get_hostp2m(d), gfn, t, &a, q, NULL); } /* Syntactic sugar: most callers will use one of these.